package com.qf.face.client.ui;


import com.alibaba.fastjson.JSONObject;
import com.qf.face.client.utils.Base64Util;
import com.qf.face.client.utils.OkHttpUtil;
import com.qf.face.client.utils.SoundUtil;
import org.opencv.core.Point;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;

import java.awt.*;
import java.awt.image.BufferedImage;


/**
 * @author 30909
 * 摄像头的适配
 */
public class FaceDetectionHub {


    static int frameWidth = 0;
    static int frameHeight = 0;
    private static JFrameGUI gui;
    private static BufferedImage nowFrame;

    /**
     * 程序入门
     */
    public static void start() {
        //人脸检测的机器人

        CascadeClassifier faceDetector = new CascadeClassifier("C:\\opencv\\haarcascade_frontalface_alt.xml");

        //打开摄像头
        VideoCapture capture = new VideoCapture();
        capture.open(0);
        if (!capture.isOpened()) {
            System.out.println("无法加载视频数据");
            return;
        }
        //获取整的宽度
        frameWidth = (int) capture.get(3);
        //获取整的宽度
        frameHeight = (int) capture.get(4);

        Mat frame = new Mat();
        while (true) {
            //读取一帧
            boolean have = capture.read(frame);

            //翻转画面
            Core.flip(frame, frame, 1);

            //人脸检测
            MatOfRect faceDetections = new MatOfRect();
            faceDetector.detectMultiScale(frame, faceDetections);


            //圈出人脸检测
            for (Rect rect : faceDetections.toArray()) {

                if (1.0 * rect.height / frame.height() > 0.6) {
                    Imgproc.rectangle(frame, new Point(rect.x, rect.y),
                            new Point(rect.x + rect.width, rect.y + rect.height),
                            new Scalar(0, 255, 255), 1);
                    //把脸截取下来
                    Mat face = new Mat(frame, rect);

                    //mat->bufferedImage
                    BufferedImage image = mat2BufferedImage(face);

                    String base64 = Base64Util.image2Base64(image);
                    //bufferedImage->user-service->face-service
                    String nickname = sign(base64);

                    //接收用户id以及用户的信息nickname

                    //绘制人名
                    Graphics graphics = gui.getGraphics();
                    graphics.setFont(new Font("宋体", Font.BOLD, 20));
                    if (nickname != null) {
                        //成功
                        graphics.setColor(Color.GREEN);
                        graphics.drawString(nickname + "识别成功",
                                frameWidth / 2 - graphics.getFontMetrics().stringWidth("识别成功") / 2,
                                frameWidth - 50);
                        SoundUtil.success();
                    } else {
                        //失败
                        graphics.setColor(Color.RED);
                        graphics.drawString(nickname + "识别失败",
                                frameWidth / 2 - graphics.getFontMetrics().stringWidth("识别失败") / 2,
                                frameWidth - 50);
                        SoundUtil.error();
                    }
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                }

            }
            if (!have) {
                break;
            }
            //给用户展示摄像头的图像信息
            if (gui == null) {
                gui = new JFrameGUI();
                gui.createWin("请针对摄像头", new Dimension(frameWidth, frameHeight));
                gui.setVisibleSelf(true);
            }
            if (!frame.empty()) {
                //刷新界面

                gui.showImage(mat2BufferedImage(frame));
                gui.repaint();
            }
            //之后校验人脸的时候应该把这一帧进行二次处理
            //考虑处理的时候，把它锁起来
//            if (!frame.empty()) {
//
//                if (nowFrame == null) {
//
//                } else {
//
//                }
//            }
        }
    }

    /**
     * Mat 转 BufferedImages
     */
    public static BufferedImage mat2BufferedImage(Mat mat) {
        //获取图片的高，宽度
        int width = mat.cols();
        int height = mat.rows();

        //获取mat的颜色通道
        int dims = mat.channels();

        //rgb颜色通道，3个颜色通道，也就是说有三个字节来表达
        //一共有多少个 width * height 个像素点，一共有多少个字节呢？
        byte[] rgbData = new byte[dims * height * width];

        //获取像素点的信息
        mat.get(0, 0, rgbData);

        //申请一个 bufferedImages
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);

        //BufferedImage 的像素点
        int[] pixels = new int[width * height];
        //像素点转化算法
        int index = 0;
        int r = 0;
        int g = 0;
        int b = 0;
        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                //彩色照片
                if (dims == 3) {
                    //计算byte 数组的角标，像素行，列的关系
                    index = (row * width + col) * dims;

                    //拿到rgb
                    r = rgbData[index] & 0xff;
                    g = rgbData[index + 1] & 0xff;
                    b = rgbData[index + 2] & 0xff;

                    r = rgbData[index] & 0xff;
                    g = rgbData[index + 1] & 0xff;
                    b = rgbData[index + 2] & 0xff;

                    //三个像素点合成一个像素点
                    pixels[row * width + col] = (0xff << 24) | (r << 16) | (g << 8) | (b << 0);

                }
            }
        }

        image.getRaster().setDataElements(0, 0, width, height, pixels);
        return image;
    }

    public static void showCamera(boolean flag) {
        if (gui == null) {
            return;
        }
        gui.setVisibleSelf(flag);
    }


    public static final String FACE_SIGN_URL = "http://localhost:9001/qf/sign";

    private static String sign(String faceBase64) {

        //请求user-service 的sing的接口
        JSONObject json = new JSONObject();

        json.put("face", faceBase64);
        String result = OkHttpUtil.getInstance().post(FACE_SIGN_URL, json.toJSONString());

        json = JSONObject.parseObject(result);
        Integer code = json.getInteger("code");

        if (code == 200) {
            //成功111
            //保存打卡记录，把打卡记录发送到服务器，服务器持久化
            return json.getJSONObject("result").getJSONObject("user").getString("nickname");

        }
        return null;
    }
}
